package repository

import (
	"fmt"
	gamedb "game/game-db"
	"game/game-db/orm"
)

type directRepository[T orm.IDbEntity] struct {
	dao            gamedb.IDao[T]
	firstKeyName   string
	relationFields []string
}

type DirectInfo struct {
	RelationFields []string
}

// 直存直取仓库实体
type IDirectRepositoryEntity interface {
	orm.IDefaultDbEntity
	DirectInfo() *DirectInfo
}

func NewDirectRepository[T IDirectRepositoryEntity](dao gamedb.IDao[T], entityTemplate T) IRepository[T] {
	var repository directRepository[T]
	repository.dao = dao
	directInfo := entityTemplate.DirectInfo()
	var relationFields []string
	if directInfo.RelationFields == nil || len(directInfo.RelationFields) <= 0 {
		primaryFieldName := dao.EntityMeta().FieldNameByColumnName(dao.EntityMeta().PrimaryKeyName())
		relationFields = make([]string, 0)
		relationFields = append(relationFields, primaryFieldName)
	} else {
		relationFields = directInfo.RelationFields
	}
	repository.firstKeyName = relationFields[0]
	repository.relationFields = relationFields
	return &repository
}

func (t *directRepository[T]) ListByKeys(keys ...interface{}) []T {
	if keys == nil || len(keys) <= 0 {
		panic("ListByKeys need keys not empty")
	}
	var keyOptions keyOptions
	for i := 0; i < len(keys) && i < len(t.relationFields); i++ {
		keyOptions.Put(t.relationFields[i], keys[i])
	}
	return getListFromDb(t.dao, &keyOptions)
}

func (t *directRepository[T]) GetByKeys(keys ...interface{}) (T, bool) {
	if keys == nil || len(keys) <= 0 {
		panic("GetByKeys need keys not empty")
	}
	var keyOptions keyOptions
	for i := 0; i < len(keys) && i < len(t.relationFields); i++ {
		keyOptions.Put(t.relationFields[i], keys[i])
	}
	return getOneFromDb(t.dao, &keyOptions)
}

func (t *directRepository[T]) Insert(entity T) error {
	return t.dao.Insert(entity)
}

func (t *directRepository[T]) InsertAll(entities []T) {
	t.dao.InsertAll(entities)
}

func (t *directRepository[T]) Update(entity T) {
	t.dao.Update(entity)
}

func (t *directRepository[T]) UpdateAll(entities []T) {
	t.dao.UpdateAll(entities)
}

func (t *directRepository[T]) Delete(entity T) {
	t.dao.Delete(entity)
}

func (t *directRepository[T]) DeleteAll(entities []T) {
	t.dao.DeleteAll(entities)
}

func (t *directRepository[T]) Scan() {
	fmt.Println("Empty")
}

func (t *directRepository[T]) LoadAll() []T {
	return t.dao.QueryWhere("")
}
